package com.cipe.cmrs.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public enum SessionHistoryRepository {
    INSTANCE;

    public static final String CURR_URL = "currUrl";
    private static final String PREV_URL = "prevUrl";
    private static final String NEXT_URL = "nextUrl";
    private static final String MARKER_INDEX = "index=";
    private static final Logger logger = LoggerFactory.getLogger(SessionHistoryRepository.class);
    private Map<String, List<String>> historyMap = new HashMap<String, List<String>>();

    public void initializeHistory(HttpSession session) {
        historyMap.put(session.getId(), new ArrayList<String>());
    }

    public void removeHistory(HttpSession session) {
        historyMap.remove(session.getId());
    }

    public void clear() {
        historyMap.clear();
    }

    public void updateSessionHistory(HttpServletRequest request) {
        String url = request.getRequestURL().toString();
        String currUrl = url.substring(url.indexOf("/secure/") + "/secure/".length());

        if (currUrl.indexOf("showDashboard.do") != -1) {
            currUrl = "refreshDashboard.do";
        }

        int markerIndex = -1;
        HttpSession session = request.getSession();
        if (StringUtils.isNotBlank(request.getQueryString())) {
            StringBuilder queryStringBuilder = new StringBuilder();
            String[] params = request.getQueryString().split("&");
            for (String param : params) {
                if (param.indexOf(MARKER_INDEX) == -1) {
                    if (queryStringBuilder.length() < 1) {
                        queryStringBuilder.append("?");
                    } else {
                        queryStringBuilder.append("&");
                    }
                    queryStringBuilder.append(param);
                } else {
                    // Back or Forward
                    markerIndex = Integer.valueOf(param.substring(MARKER_INDEX.length()));
                }
            }
            currUrl += queryStringBuilder.toString();
        }

        String prevUrl = "";
        String nextUrl = "";
        List<String> urls = historyMap.get(session.getId());
        if (urls == null) {
            urls = new ArrayList<String>();
            historyMap.put(session.getId(), urls);
        }
        if (markerIndex != -1) {
            if (markerIndex - 1 >= 0) {
                prevUrl = urls.get(markerIndex - 1);
                prevUrl += getIndexParam(prevUrl, markerIndex - 1);
            }

            if (markerIndex + 1 < urls.size()) {
                nextUrl = urls.get(markerIndex + 1);
                nextUrl += getIndexParam(nextUrl, markerIndex + 1);
            }
        } else {
            String prevNextUrl = (String) session.getAttribute(NEXT_URL);
            if (StringUtils.isBlank(prevNextUrl)) {
                if (!urls.isEmpty()) {
                    prevUrl = urls.get(urls.size() - 1);
                    prevUrl += getIndexParam(prevUrl, urls.size() - 1);
                }
                urls.add(currUrl);
            } else {
                prevNextUrl = prevNextUrl.substring(0, prevNextUrl.indexOf(MARKER_INDEX) - 1);
                String prevCurrUrl = (String) session.getAttribute(CURR_URL);
                String prevBackUrl = (String) session.getAttribute(PREV_URL);
                if (StringUtils.isNotBlank(prevBackUrl)) {
                    prevBackUrl = prevBackUrl.substring(0, prevBackUrl.indexOf(MARKER_INDEX) - 1);
                }

                int i = urls.size() - 1;
                for (; i > 0; i--) {
                    if (prevNextUrl.equals(urls.get(i)) && prevCurrUrl.equals(urls.get(i - 1))) {
                        if (StringUtils.isBlank(prevBackUrl) || prevBackUrl.equals(urls.get(i - 2))) {
                            break;
                        }
                    }
                }

                for (int j = urls.size() - 1; j >= i; j--) {
                    urls.remove(j);
                }

                prevUrl = prevCurrUrl;
                prevUrl += getIndexParam(prevUrl, urls.size() - 1);

                urls.add(currUrl);
            }
        }

        session.setAttribute(PREV_URL, prevUrl);
        session.setAttribute(CURR_URL, currUrl);
        session.setAttribute(NEXT_URL, nextUrl);
        logger.debug("BACK   : " + prevUrl);
        logger.debug("CURR   : " + currUrl);
        logger.debug("FORWARD: " + nextUrl);
    }

    private String getIndexParam(String url, int index) {
        String result = "";
        if (url.indexOf("?") == -1) {
            result = "?" + MARKER_INDEX + index;
        } else {
            result = "&" + MARKER_INDEX + index;
        }
        return result;
    }
}
